#include <QtGui>

#include "gui/MainWindow31.h"
#include "strategies.h"
#include "Results.h"

#include <iostream>
using std::cout;
using std::endl;

MainWindow31::MainWindow31(QWidget *parent)
  : QMainWindow(parent), haveGame(false), gameIsConnected(false),
    agentTemplate(NULL),
    numGames(0),numWins(0),streak(0)
{
//   QResource::registerResource("resource/deck.rcc");
  srand(time(NULL));

  setupMenus();
  setupWidgets();

//   setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
  move(100,100);
  resize(400,500);
  setWindowTitle(tr("31"));
}

MainWindow31::~MainWindow31() {
  deleteGame();
}

void MainWindow31::gameCompleted()
{
  QString title, message, streakMessage;
  QMessageBox::StandardButtons buttons, response;

  numGames++;
  buttons = QMessageBox::Ok | QMessageBox::Close;
  if (game->getWinner() == humanPosition) { // you won!
    numWins++;
    if (streak > 0)
      streak++;
    else
      streak=1;
    title = tr("You won!");
    message = tr("Congratulations, you won the game!\n");
    streakMessage = tr("%1 win streak.\n").arg(streak);
  } else {// you lost
    if (streak < 0)
      streak--;
    else
      streak=-1;
    title =  tr("You lost!");
    message = tr("Sorry, you lost the game!\n");
    streakMessage = tr("%1 loss streak.\n").arg(-streak);
  }
  message += tr("You have won %1 of %2 games, with a ").arg(numWins).arg(numGames);
  message += streakMessage;
  message += tr("Click OK to start a new game.");

  response = QMessageBox::question(this, title, message, buttons,
                                   QMessageBox::Close);

  if (response == QMessageBox::Ok)
    startNewGame();
}

void MainWindow31::startNewGame()
{
  deleteGame();
  messageText->clear();
  setupPlayers();

  game = new GUIGameManager(players);
  haveGame = true;
  buildGameConnections();

  playArea->startGame(game, const_cast<const Player**>(players), humanPosition);
  game->run();
}

void MainWindow31::loadAgents() {
  QString f =
      QFileDialog::getOpenFileName(this, "Select an agent file...");
  if (f.isEmpty())
    return;
  string fileName = string(f.toAscii().data());

  bool ok;
  int agentNumber = QInputDialog::getInteger(this, "Which agent entry?",
                                             "Agent number:", 1, 1, 10, 1, &ok);
  if (!ok)
    return;

  cout << "Loading agent " << agentNumber << " from " << fileName << endl;

  AgentGenome** templateList = Results::readFromFile(fileName, agentNumber);
  agentNumber--;
  agentTemplate = templateList[agentNumber];
  for (int i=0; i<agentNumber; i++)
    delete templateList[i];
  delete [] templateList;

  QString message = "Successfully loaded the agent.\n";
//   message += agentTemplate->toShortString().c_str();
  message += "Start a new game to play against the new agent.";
  QMessageBox msgBox;
  msgBox.setText(message);
  msgBox.setDetailedText(agentTemplate->toShortString().c_str());
  msgBox.setStandardButtons(QMessageBox::Ok);
  msgBox.setDefaultButton(QMessageBox::Ok);
  msgBox.setSizeGripEnabled(true);
  msgBox.setMaximumSize(1000,1000);
  int ret = msgBox.exec();
//   QMessageBox::information(this, "Agent Loaded", message, QMessageBox::Ok);
}

void MainWindow31::setupMenus() {
  QMenu *gameMenu = menuBar()->addMenu(tr("&Game"));

  QList<QKeySequence> newShortcutList;
  QAction *newAction = gameMenu->addAction(tr("&New Game"));
  newShortcutList << QKeySequence(tr("Ctrl+N")) << QKeySequence(tr("F2"));
  newAction->setShortcuts(newShortcutList);

  QList<QKeySequence> loadShortcutList;
  QAction *loadAction = gameMenu->addAction(tr("&Load Agent..."));
  loadShortcutList << QKeySequence(tr("Ctrl+L")) << QKeySequence(tr("Ctrl+O"));
  loadAction->setShortcuts(loadShortcutList);

  QAction *quitAction = gameMenu->addAction(tr("&Quit"));
  quitAction->setShortcut(QKeySequence(tr("Ctrl+Q")));

  // Need to connect this to the game
  connect(newAction, SIGNAL(triggered()), this, SLOT(startNewGame()));
  connect(loadAction, SIGNAL(triggered()), this, SLOT(loadAgents()));
  connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
}

void MainWindow31::setupWidgets() {

  QFrame* center = new QFrame;
  QVBoxLayout* centerLayout = new QVBoxLayout;

  playArea = new PlayArea;
  centerLayout->addWidget(playArea);

  knockButton = new QPushButton("Knock");
  centerLayout->addWidget(knockButton);

  messageText = new QTextEdit;
  messageText->setReadOnly(true);
  messageText->setTextInteractionFlags(Qt::TextSelectableByMouse);
  centerLayout->addWidget(messageText);

  center->setLayout(centerLayout);
  setCentralWidget(center);
}

void MainWindow31::setupPlayers() {

  int agentPosition = Query::RandomChoice(2);
  humanPosition = abs(1-agentPosition);
  players[agentPosition] = getAgentPlayer(agentPosition);
  players[humanPosition] = new HumanPlayer(humanPosition);
}

Player* MainWindow31::getAgentPlayer(int position) {

  if (agentTemplate)
    return dynamic_cast<Player*>(agentTemplate->buildAgent(position));

  DiscardStrategy* agentDiscardStrategy = new MaxMinDiscardStrategy(100);
  DrawingStrategy* agentDrawingStrategy = new SimpleDrawingStrategy(100);
  agentDrawingStrategy->setDiscardStrategy(agentDiscardStrategy);
  agentDrawingStrategy->setExecutionParameter(0, 50);
  KnockingStrategy* agentKnockingStrategy = new SimEVKnockingStrategy(100);
  agentKnockingStrategy->setExecutionParameter(0, 60);
  agentKnockingStrategy->setExecutionParameter(1, 80);

  DiscardStrategy* agentEndDiscardStrategy = new MaxScoreDiscardStrategy(100);
  DrawingStrategy* agentEndDrawingStrategy = new ExpValueDrawingStrategy(100);
  agentEndDrawingStrategy->setDiscardStrategy(agentEndDiscardStrategy);

  return dynamic_cast<Player*>(new Agent31(position, agentKnockingStrategy,
                                                     agentDrawingStrategy,
                                                     agentDiscardStrategy,
                                                     agentEndDrawingStrategy,
                                                     agentEndDiscardStrategy));

}

void MainWindow31::deleteGame() {
  if (haveGame) {
    for (int i=0; i<NUM_PLAYERS; i++) {
      QObject* qplayer = dynamic_cast<QObject*>(players[i]);
      if (!qplayer)
        delete players[i];
      else
        qplayer->deleteLater();
    }
    QObject* qgame = dynamic_cast<QObject*>(game);
    if (qgame)
      qgame->deleteLater();

    haveGame=false;
    gameIsConnected=false;
  }
}

void MainWindow31::buildGameConnections() {

  if (!haveGame || gameIsConnected)
    return;

  HumanPlayer* human = dynamic_cast<HumanPlayer*>(players[humanPosition]);
  if (human) {
    connect(playArea, SIGNAL(drawPileClicked()),
            human, SLOT(selectDrawPile()));
    connect(playArea, SIGNAL(discardPileClicked()),
            human, SLOT(selectDiscardPile()));
    connect(playArea, SIGNAL(playerHandClicked(int)),
            human, SLOT(selectHandCard(int)));
    connect(knockButton, SIGNAL(clicked()),
            human, SLOT(selectKnock()));
    connect(human, SIGNAL(turnComplete(int, Move)),
            game, SLOT(completeHumanTurn(int, const Move&)));
    connect(human, SIGNAL(humanDrawOccurred(int)), this, SLOT(update()));
    connect(human, SIGNAL(humanPickOccurred(int)), this, SLOT(update()));
    connect(human, SIGNAL(humanDiscardOccurred(int)), this, SLOT(update()));
  }

  connect(game, SIGNAL(gameReport(QString)),
          messageText, SLOT(append(const QString&)));
  connect(game, SIGNAL(agentTurnOccurred(int)), this, SLOT(update()));
  connect(game, SIGNAL(gameOver()), playArea, SLOT(revealHands()));
  connect(game, SIGNAL(gameOver()), this, SLOT(gameCompleted()));

  gameIsConnected=true;
}


